package org.myframework.codeutil;

import org.myframework.util.DateUtil;
import org.myframework.util.FileUtil;
import org.myframework.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class CodeGenerator {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    CodeTool tool = new CodeTool();

    private String pkgPrefix = "com.linkage";

    private String module = "";

    private String subModule = "region";

    private String catalog = null;

    private String tablePrefix = "";

    private String tableName = "GROUP_REGION_AUTO_CLAIM";

    private String javaSource = "D://CODEGEN//java//";

    private String webapp = "D://CODEGEN//webapp//";

    private String resources = "D://CODEGEN//resources//";

    /**
     * 模板路径
     */
    private String basedir = "";

    private String propertiesFile = "jdbc.properties";

    private String classVar;

    private String className;

    private String keyVar;

    private String keyType;

    private String jspDir;

    private String packageName;


    public String getPropertiesFile() {
        return propertiesFile;
    }

    public void setPropertiesFile(String propertiesFile) {
        this.propertiesFile = propertiesFile;
    }

    public String getBasedir() {
        return basedir;
    }

    public void setBasedir(String basedir) {
        this.basedir = basedir;
    }

    private List<Column> getPkColumns(List<Column> lsColumns) {
        List<Column> lsColumnTemp = new ArrayList<Column>(lsColumns.size());
        List<Column> pkColumns = new ArrayList<Column>(2);
        for (Column column : lsColumns) {
            if (column.isColumnKey()) {
                pkColumns.add(column);
            } else {
                lsColumnTemp.add(column);
            }
        }
        tool.put("columnResult", lsColumnTemp);
        tool.put("pkResult", pkColumns);
        return pkColumns;
    }

    public void initCodeTool(List<Column> lsColumns) throws Exception {
        classVar = StringUtil.toBeanPatternStr(tableName.substring(tablePrefix
                .length()));
        className = StringUtil.firstCharUpperCase(classVar);
        pkgPrefix = pkgPrefix
                + (StringUtil.isEmpty(module) ? "" : ("." + module))
                + (StringUtil.isEmpty(subModule) ? "" : ("." + subModule));
        jspDir = (StringUtil.isEmpty(module) ? "" : ("/" + module))
                + (StringUtil.isEmpty(subModule) ? "" : ("/" + subModule));
        tool.put("tableName", tableName);
        tool.put("className", className);
        tool.put("module", module);
        tool.put("subModule", subModule);
        tool.put("classVar", classVar);
        tool.put("packagePrefix", pkgPrefix);
        tool.put("packagePrefixDir", pkgPrefix.replace('.', '/'));
        tool.put("packageName", packageName);
        tool.put("jspDir", jspDir);

        // 把主键和非主键分别放入tool
        List<Column> pkResult = getPkColumns(lsColumns);
        pkResult = pkResult.size() != 0 ? pkResult : lsColumns;
        int pkCnt = pkResult.size();
        if (pkCnt > 1) {
            logger.debug("创建复合主键类;主键字段>>>>>>" + pkResult);
            keyType = "PK";
            keyVar = "pk";
            tool.put("keyType", keyType);
            tool.put("keyVar", keyVar);
        } else {
            Column column = pkResult.get(0);
            logger.debug("主键字段>>>>>>" + column);
            keyType = column.getDataType();
            keyVar = column.getJavaName();
            String keyColumn = column.getColumnName();
            tool.put("keyType", keyType);
            tool.put("keyVar", keyVar);
            tool.put("keyColumn", keyColumn);
            tool.put("keyVar0", StringUtil.firstCharUpperCase(keyVar));
        }

        tool.put("needUpdate", true);
        tool.put("date", DateUtil.getCurrentDay());
        tool.put("author", System.getProperty("user.name"));

    }

    public void createCodeByConf() throws Exception {
        // step 1
        Properties jdbcProperties = FileUtil.loadProperties(basedir + propertiesFile);
        String tmplDir = basedir + jdbcProperties.getProperty("tmplDir", "templates");
        File dir = new File(tmplDir);
        if (dir.exists() && dir.isDirectory()) {
            tool.setTmplDir(tmplDir);
        } else {
            tool.setTmplDir(CodeTool.RESOURCE_PATH_PREFIX + tmplDir);
        }

        tool.initVelocity();
        // step 2
        for (Object key : jdbcProperties.keySet()) {
            if (tool.get(key.toString()) == null)
                tool.put(key.toString(), jdbcProperties.get(key));
        }
        // step 3
        String fileName = jdbcProperties.getProperty("cfgFileName", "templates.cfg");
        List<String> genFiles = getGenFileList(basedir + fileName);
        createFileByCfg(genFiles);
    }

    public void createFileByCfg(List<String> genFiles) throws Exception {
        for (String file : genFiles) {
            logger.info("=======❤❤❤❤❤❤❤❤=== CodeGenerator START WORK!!!===========");
            String[] props = file.split(";");
            if (props.length < 3) {
                logger.error(file + " >>配置不正确，配置格式应该是<文件描述>;<文件路径>;<模板文件名>");
                continue;
            }
            logger.info("生成源码配置信息 ：" + file);
            String filePath = tool.getText(props[1].trim());
            String vmFile = props[2].trim();
            tool.setAbsolutePath(filePath);
            tool.setTmplFile(vmFile);
            tool.createFileByTmpl();
            logger.info("=======❤❤❤❤❤❤❤❤=== CodeGenerator END WORK!!!===========");
        }
    }

    /**
     * 获取待生成源码列表
     *
     * @return
     * @throws Exception
     */
    private List<String> getGenFileList(String fileName) throws Exception {
        List<String> genFiles = new ArrayList<String>();
        InputStream in = FileUtil.getInputStream(fileName);
        Reader fr = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(fr);
        while (br.ready()) {
            String line = br.readLine();
            if (!line.startsWith("#") && !"".equals(line.trim()))
                genFiles.add(line);
        }
        br.close();
        fr.close();
        return genFiles;
    }

    public String getPkgPrefix() {
        return pkgPrefix;
    }

    public void setPkgPrefix(String pkgPrefix) {
        this.pkgPrefix = pkgPrefix;
    }

    public String getModule() {
        return module;
    }

    public void setModule(String module) {
        this.module = module;
    }

    public String getSubModule() {
        return subModule;
    }

    public void setSubModule(String subModule) {
        this.subModule = subModule;
    }

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public void setJavaSource(String javaSource) {
        this.javaSource = javaSource;
    }

    public void setWebapp(String webapp) {
        this.webapp = webapp;
    }

    public void setResources(String resources) {
        this.resources = resources;
    }

    public void setTablePrefix(String tablePrefix) {
        this.tablePrefix = tablePrefix;
    }

    @Override
    public String toString() {
        return "CodeGenerator [pkgPrefix=" + pkgPrefix + ", module=" + module
                + ", subModule=" + subModule + ", tableName=" + tableName
                + ", javaSource=" + javaSource + ", webapp=" + webapp
                + ", resources=" + resources + ", classVar=" + classVar
                + ", className=" + className + ", keyVar=" + keyVar
                + ", keyType=" + keyType + ", jspDir=" + jspDir
                + ", packageName=" + packageName + "]";
    }

}
